package com.nineclock.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.aliyun.oss.OSS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.nineclock.common.constant.NcConstant;
import com.nineclock.common.constant.SMSConstant;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.oss.OssProperties;
import com.nineclock.common.threadlocal.CurrentUserHolder;
import com.nineclock.common.utils.BeanHelper;
import com.nineclock.common.utils.UUIDUtils;
import com.nineclock.message.enums.MessageTypeEnum;
import com.nineclock.message.pojo.NcMessage;
import com.nineclock.system.config.HxImManager;
import com.nineclock.system.dto.*;
import com.nineclock.system.mapper.*;
import com.nineclock.system.pojo.*;
import com.nineclock.system.service.SmsService;
import com.nineclock.system.service.SysCompanyService;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * @author 黑马程序员
 * @Company http://www.ithiema.com
 * @Version 1.0
 */
@Service
@Slf4j
public class SysCompanyServiceImpl implements SysCompanyService {

    @Autowired
    SysCompanyMapper companyMapper;

    @Autowired
    SysCompanyUserMapper companyUserMapper;

    @Autowired
    SysCompanyUserRoleMapper companyUserRoleMapper;

    @Autowired
    SysRoleMapper roleMapper;

    @Autowired
    SmsService smsService;

    @Autowired
    SysUserMapper userMapper;

    @Override
    public SysCompanyDTO queryCompanyInfo() {

        //获取当前的企业id
        Long companyId = CurrentUserHolder.get().getCompanyId();

        //根据id获取企业信息
        SysCompany company = companyMapper.selectById(companyId);

        if(company == null){
            throw new NcException(ResponseEnum.COMPANY_NOT_FOUND);
        }

        //把pojo转换为 dto
        SysCompanyDTO companyDTO = BeanHelper.copyProperties(company, SysCompanyDTO.class);

        return companyDTO;
    }

    @Autowired
    OSS oss;

    @Autowired
    OssProperties ossProperties;

    @Override
    public String uploadOSS(MultipartFile file) throws IOException {
        if(file == null){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
        // 判断文件的类型
        String type = file.getContentType();
        //如果不是我们需要的类型之一
        if(! NcConstant.ALLOWED_IMG_TYPES.contains(type)){
            throw new NcException(ResponseEnum.INVALID_FILE_TYPE);
        }
        // 判断文件的大小
        long size = file.getSize();
        if(size > NcConstant.maxFileSize){
            throw new NcException(ResponseEnum.FILE_SIZE_EXCEED_MAX_LIMIT);
        }

        //获取唯一的文件名称  sdflkjas23dflkasdlfkasdlkj09asldf.gif
        String uuid = UUIDUtils.getUUID();
        //获取文件的后缀(1. 获取原始文件名称 2. 截取后缀名)
        String originalFilename = file.getOriginalFilename();
        //获取 最后一个 . 所在索引
        int index = originalFilename.lastIndexOf(".");
        String extendName = originalFilename.substring(index);// .gif
        //拼接文件名
        String fileName = uuid + extendName;

        //建议不关闭 oss客户端
        oss.putObject(ossProperties.getBucketName(), fileName, file.getInputStream());
        //返回 文件的网络路径
        String host = ossProperties.getHost();
        //拼接 网络地址
        String imgPath = String.format(host, ossProperties.getBucketName()) + fileName;

        return imgPath;
    }

    @Override
    public void updateCompanyInfo(SysCompanyDTO companyDTO) {
        if(companyDTO == null){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        //获取企业id
        Long companyId = CurrentUserHolder.get().getCompanyId();

        //从数据库获取 企业信息
        SysCompany company = companyMapper.selectById(companyId);
        if(company == null){
            throw new NcException(ResponseEnum.COMPANY_NOT_FOUND);
        }
        //更新数据
        company.setName(companyDTO.getName());
        company.setLogo(companyDTO.getLogo());

        //更新数据库
        companyMapper.updateById(company);
    }

    @Override
    public SysCompanyUserDTO getCurrentAdmin() {
        //获取企业id
        Long companyId = CurrentUserHolder.get().getCompanyId();
        //获取当前企业的管理员信息
        SysCompanyUser currentAdmin = companyMapper.getCurrentAdmin(companyId);

        if(currentAdmin == null){
            throw new NcException(ResponseEnum.COMPANY_ADMIN_NOT_EXISTS);
        }


        return BeanHelper.copyProperties(currentAdmin, SysCompanyUserDTO.class);
    }

    /**
     * 1. 健壮性判断
     * 2. 验证新管理员是否存在
     * 3. 校验验证码
     * 4. 删除原来主管理员 关联信息
     * 5. 添加新主管理员关系
     *
     * @param sysChangeMainManagerDTO
     */
    @Override
    public void changeSysAdmin(SysChangeMainManagerDTO sysChangeMainManagerDTO) {
        Long companyId = CurrentUserHolder.get().getCompanyId();
        //健壮性判断
        if(sysChangeMainManagerDTO == null || sysChangeMainManagerDTO.getUserId() == null || sysChangeMainManagerDTO.getCode() == null){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        //获取新管理员的员工信息
        SysCompanyUser companyUser = companyUserMapper.selectById(sysChangeMainManagerDTO.getUserId());
        if(companyUser == null){
            throw new NcException(ResponseEnum.USER_NOT_FOUND);
        }
        //校验验证码
        Boolean flag = smsService.verify(companyUser.getMobile(), SMSConstant.SMS_TYPE_CHANGE_MANAGER, sysChangeMainManagerDTO.getCode());
        if(!flag){
            throw new NcException(ResponseEnum.CODE_IMAGE_ERROR);
        }


        //获取原来的主管理员
        SysCompanyUser currentAdmin = companyMapper.getCurrentAdmin(companyId);
        //获取主管理员角色对象
        LambdaQueryWrapper<SysRole> roleQw = new LambdaQueryWrapper<>();
        roleQw.eq(SysRole::getCompanyId,companyId );
        roleQw.eq(SysRole::getRoleName, "ROLE_ADMIN_SYS");

        SysRole role = roleMapper.selectOne(roleQw);

        //删除原来主管理员 关联信息
        LambdaQueryWrapper<SysCompanyUserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysCompanyUserRole::getCompanyId, companyId);
        wrapper.eq(SysCompanyUserRole::getRoleId, role.getId());
        wrapper.eq(SysCompanyUserRole::getCompanyUserId, currentAdmin.getId());

        companyUserRoleMapper.delete(wrapper);


        //添加新主管理员关系
        SysCompanyUserRole companyUserRole = new SysCompanyUserRole();

        companyUserRole.setCompanyId(companyId);
        companyUserRole.setCompanyUserId(sysChangeMainManagerDTO.getUserId());
        companyUserRole.setRoleId(role.getId());

        companyUserRoleMapper.insert(companyUserRole);
    }

    @Override
    public List<SysCompanyDTO> queryCompanyByName(String keyword) {
        if(keyword == null){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        LambdaQueryWrapper<SysCompany> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(SysCompany::getName, keyword);

        List<SysCompany> companyList = companyMapper.selectList(wrapper);
        if(CollectionUtil.isEmpty(companyList)){
            throw new NcException(ResponseEnum.COMPANY_NOT_FOUND);
        }

        return BeanHelper.copyWithCollection(companyList, SysCompanyDTO.class);
    }

    @Autowired
    RocketMQTemplate rocketMQTemplate;

    @Autowired
    HxImManager hxImManager;

    /**
     * 1. 健壮性判断
     * 2. 对用户信息更新
     * 3. 添加员工信息
     * @param sysApplyJoinCompanyUserDTO
     */
    @Override
    public void applyJoinCompany(SysApplyJoinCompanyUserDTO sysApplyJoinCompanyUserDTO) {
        if(sysApplyJoinCompanyUserDTO == null || sysApplyJoinCompanyUserDTO.getUserName() == null){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        //先查询用户信息
        SysUser user = userMapper.selectById(sysApplyJoinCompanyUserDTO.getUserId());
        if(user == null){
            throw new NcException(ResponseEnum.USER_NOT_FOUND);
        }

        user.setUsername(sysApplyJoinCompanyUserDTO.getUserName());
        user.setEmail(sysApplyJoinCompanyUserDTO.getEmail());
        user.setUpdateTime(new Date());
        user.setLastLoginCompanyId(sysApplyJoinCompanyUserDTO.getCompanyId());
        //更新用户表
        userMapper.updateById(user);


        //新增员工信息
        SysCompanyUser companyUser = new SysCompanyUser();
        companyUser.setUserId(user.getId());
        companyUser.setUserName(user.getUsername());
        companyUser.setEnable((short)0); //没有审核通过加入企业，所以设置为 0
        companyUser.setTimeEntry(new Date());
        companyUser.setRemark(sysApplyJoinCompanyUserDTO.getApplyReason());
        companyUser.setEmail(sysApplyJoinCompanyUserDTO.getEmail());
        companyUser.setPost(sysApplyJoinCompanyUserDTO.getPost());
        companyUser.setMobile(sysApplyJoinCompanyUserDTO.getMobile());
        companyUser.setCompanyId(sysApplyJoinCompanyUserDTO.getCompanyId());
        companyUser.setCompanyName(sysApplyJoinCompanyUserDTO.getCompanyName());
        companyUser.setImageUrl(sysApplyJoinCompanyUserDTO.getImageUrl());
        companyUser.setCreateTime(new Date());


        companyUserMapper.insert(companyUser);

        //查询系统主管理员
        SysCompanyUser currentAdmin = companyMapper.getCurrentAdmin(sysApplyJoinCompanyUserDTO.getCompanyId());


        //申请加入企业完成后， 需要提醒管理员 进行审核
        //消息推送
        NcMessage message = new NcMessage();
        message.setMessageType(MessageTypeEnum.COMPANY_APPLY.getType());
        message.setCreateTime(new Date());
        message.setCompanyId(sysApplyJoinCompanyUserDTO.getCompanyId() + "");
        message.setTitle(MessageTypeEnum.COMPANY_APPLY.getTitle());
        message.setContent(sysApplyJoinCompanyUserDTO.getUserName() + " 申请加入企业，请及时审批");
        message.setUseStatus(0);
        message.setAudience(MessageTypeEnum.COMPANY_APPLY.getAudience());
        message.setTargets(Arrays.asList(currentAdmin.getMobile())); //主管理员的手机号码
        message.setApproveStatue(0);
        message.setApplyUserId(user.getId());
        message.setApplyUsername(sysApplyJoinCompanyUserDTO.getUserName());
        message.setApproveUserId(currentAdmin.getUserId());
        message.setApproveUsername(currentAdmin.getUserName());


        //推送消息 到mq
        rocketMQTemplate.convertAndSend("messagePushTopic", message);

        //注册 用户信息到环信云
        SysUser user1 = new SysUser();
        user1.setUsername(user.getMobile());
        user1.setPassword("123456");
        hxImManager.registerUser2HuanXing(user1);


    }

    @Override
    public void allowedJoinCompany(SysAllowedJoinCompanyUserDTO allowedJoinCompanyUserDTO) {
        if(allowedJoinCompanyUserDTO == null || allowedJoinCompanyUserDTO.getApplyUserId() == null){
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }

        //1. 更新员工信息
        LambdaQueryWrapper<SysCompanyUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysCompanyUser::getUserId, allowedJoinCompanyUserDTO.getApplyUserId());
        wrapper.eq(SysCompanyUser::getCompanyId, CurrentUserHolder.get().getCompanyId());
        SysCompanyUser companyUser = companyUserMapper.selectOne(wrapper);
        //更新信息
        //更新状态值
        companyUser.setEnable((short)(allowedJoinCompanyUserDTO.getApproved() ? 1:  0));
        //更新状态信息
        companyUser.setRemark(allowedJoinCompanyUserDTO.getRemark());
        companyUser.setUpdateTime(new Date());
        //更新
        companyUserMapper.updateById(companyUser);

        //2. 推送消息
        //2.1 推送消息 ， 消费方 只是用来更新mongo中的信息
        rocketMQTemplate.convertAndSend("allowedJoinCompanyTopic", allowedJoinCompanyUserDTO.getNotifyMsgId());
        //2.2 推送消息, 负责推送消息给申请人(只是使用原来的消费监听器)
        NcMessage message = new NcMessage();
        message.setMessageType(MessageTypeEnum.COMPANY_APPLY_PASS.getType()) ;
        message.setCreateTime(new Date());
        message.setCompanyId(CurrentUserHolder.get().getCompanyId() + "");
        message.setTitle(MessageTypeEnum.COMPANY_APPLY_PASS.getTitle());
        message.setContent("您加入企业的申请已通过!");
        message.setAudience(MessageTypeEnum.COMPANY_APPLY_PASS.getAudience());
        message.setApproveResult(allowedJoinCompanyUserDTO.getRemark());
        message.setApplyUserId(allowedJoinCompanyUserDTO.getApplyUserId());
        message.setApplyUsername(companyUser.getUserName());

        message.setApproveUserId(CurrentUserHolder.get().getId()); //审批 用户id
        message.setApplyUsername(CurrentUserHolder.get().getUsername());
        message.setTargets(Arrays.asList(companyUser.getMobile())); //申请人 手机号(作为别名 推送消息)

        rocketMQTemplate.convertAndSend("messagePushTopic", message);
    }

    @Override
    public List<SysCompanyDTO> queryCompanyListByUserId(Long userId) {
        List<SysCompany> companyList = companyMapper.queryCompanyListByUserId(userId);
        if (CollectionUtil.isEmpty(companyList)){
            throw new NcException(ResponseEnum.USER_NOT_JOIN_COMPANY);
        }

        return BeanHelper.copyWithCollection(companyList, SysCompanyDTO.class);
    }
}
